#include "fs.h"
#include "sem.h"
#include "irq.h"
#include "cond.h"
#include "lock.h"
#include "sched.h"
#include "common.h"
#include "screen.h"
#include "barrier.h"
#include "syscall.h"
uint64_t (*syscall[NUM_SYSCALLS])();
void system_call_helper(uint64_t fn, uint64_t arg1, uint64_t arg2, uint64_t arg3)
{
    current_running->user_context.cp0_epc = current_running->user_context.cp0_epc + 4;
    uint64_t ret = syscall[fn](arg1, arg2, arg3);
    current_running->user_context.regs[2] = ret;
}
uint64_t sys_get_timer()
{
    invoke_syscall(SYSCALL_GET_TIMER, 0, 0, 0);
}
void sys_yield()
{
    invoke_syscall(SYSCALL_YIELD,0,0,0);
}
void sys_spawn(task_info_t *info)
{
    invoke_syscall(SYSCALL_SPAWN,(uint64_t)info, 0, 0);
}

void sys_exit(void)
{
    invoke_syscall(SYSCALL_EXIT, 0, 0, 0);
}

void sys_sleep(uint32_t time)
{
    invoke_syscall(SYSCALL_SLEEP, time, 0, 0);
}

int sys_kill(pid_t pid)
{
    invoke_syscall(SYSCALL_KILL,pid, 0, 0);
}

int sys_waitpid(pid_t pid)
{
    invoke_syscall(SYSCALL_WAITPID,pid, 0, 0);
}

void sys_write(char *buff)
{
    invoke_syscall(SYSCALL_WRITE, (uint64_t)buff, 0, 0);
}

void sys_reflush()
{
    invoke_syscall(SYSCALL_REFLUSH, 0, 0, 0);
}

void sys_move_cursor(int x, int y)
{
    invoke_syscall(SYSCALL_CURSOR, x, y, 0);
}

void mutex_lock_init(mutex_lock_t *lock)
{
    invoke_syscall(SYSCALL_MUTEX_LOCK_INIT, (uint64_t)lock, 0, 0);
}

void mutex_lock_acquire(mutex_lock_t *lock)
{
    invoke_syscall(SYSCALL_MUTEX_LOCK_ACQUIRE, (uint64_t)lock, 0, 0);
}

void mutex_lock_release(mutex_lock_t *lock)
{
    invoke_syscall(SYSCALL_MUTEX_LOCK_RELEASE, (uint64_t)lock, 0, 0);
}
int binsemop(int binsem_id, int op)
{
    invoke_syscall(SYSCALL_BINSEM_OP,binsem_id, op, 0);
}
int binsemget(int key)
{
    invoke_syscall(SYSCALL_BINSEM_GET,key, 0, 0);
}
void condition_init(condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_INIT,(uint64_t)condition,0,0);
}

void condition_wait(mutex_lock_t *lock, condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_WAIT,(uint64_t)lock,(uint64_t)condition,0);
}
void condition_signal(condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_SIGNAL,(uint64_t)condition,0,0);
}

void condition_broadcast(condition_t *condition)
{
    invoke_syscall(SYSCALL_CONDITION_BROADCAST,(uint64_t)condition,0,0);
}

void semaphore_init(semaphore_t *s, int val)
{
}
void semaphore_up(semaphore_t *s)
{
}

void semaphore_down(semaphore_t *s)
{
}

void barrier_init(barrier_t *barrier, int goal)
{
    invoke_syscall(SYSCALL_BARRIER_INIT,(uint64_t)barrier,goal,0);
}

void barrier_wait(barrier_t *barrier)
{
    invoke_syscall(SYSCALL_BARRIER_WAIT,(uint64_t)barrier,0,0);
}

int sys_read_shell_buff()
{
    invoke_syscall(SYSCALL_READ_SHELL_BUFF,0, 0, 0);
}

void sys_process_show(void)
{
    invoke_syscall(SYSCALL_PS,0,0,0);
}
void sys_screen_clear(int line1, int line2)
{
    invoke_syscall(SYSCALL_SCREEN_CLEAR,line1,line2,0);
}
void sys_screen_scroll(int line1, int line2)
{
    invoke_syscall(SYSCALL_SCREEN_SCROLL,line1,line2,0);
}
pid_t sys_getpid()
{
    invoke_syscall(SYSCALL_GETPID,0,0,0);
}


int mbox_open(char *name)
{
    invoke_syscall(SYSCALL_MBOX_OPEN,(uint64_t)name,0,0);
}
void mbox_close(int mboxid)
{
    invoke_syscall(SYSCALL_MBOX_CLOSE,mboxid,0,0);
}
void mbox_send(int mboxid, void *msg, int msg_length)
{
    invoke_syscall(SYSCALL_MBOX_SEND,mboxid,(uint64_t)msg,msg_length);
}
void mbox_recv(int mboxid, void *msg, int msg_length)
{
    invoke_syscall(SYSCALL_MBOX_RECV,mboxid,(uint64_t)msg,msg_length);
}
void sys_mkfs()
{
}

int sys_mkdir(char *name)
{
}

int sys_readdir(char *name)
{
}

int sys_enterdir(char *name)
{
}

int sys_rmdir(char *name)
{
}

int sys_print_fs(char *name)
{
}

int sys_mknod(char *name)
{
}

int sys_fopen(char *name, uint32_t access)
{
}

int sys_fwrite(uint32_t fd, char *buff, uint32_t size)
{
}

int sys_cat(char *name)
{
}

int sys_fread(uint32_t fd, char *buff, uint32_t size)
{
}

int sys_close(uint32_t fd)
{
}

uint32_t sys_net_recv(uint64_t buf_addr, uint64_t size, uint64_t num)
{
    invoke_syscall(SYSCALL_NET_RECV,buf_addr,size,num);
}

void sys_net_send(uint64_t buf_addr, uint64_t size, uint64_t num)
{
    invoke_syscall(SYSCALL_NET_SEND,buf_addr,size,num);
}
void sys_spawn_argv(task_info_t *info,unsigned int a0,unsigned int a1)
{
    invoke_syscall(SYSCALL_SPAWN_ARGV,(uint64_t)info, a0, a1);
}
void sys_init_mac()
{
}